package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repositoty.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateServiceImpl implements IStrategyTemplateSearchService {

    @Autowired
    private StrategyTemplateRepository strategyTemplateRepository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private TransportClient client;

    @Override
    public void saveOrUpdate(StrategyTemplate template) {
        strategyTemplateRepository.save(template);
    }

    @Override
    public List<Map<String, Object>> getThemeCommend() {
        List<Map<String,Object>> list = new ArrayList<>();
        List<StatisVO> themeVos = conditionGroup("themeGroup","themeId","themeName",null);
        if(themeVos.size() > 10){
            themeVos.subList(0,10);
        }
        Map<String,Object> map = null;
        for (StatisVO vo : themeVos) {
            map = new HashMap<>();
            map.put("theme",vo);
            map.put("dests",this.getDestByThemeId(vo.getId()));
            list.add(map);
        }
        return list;
    }

    private List<StatisVO> getDestByThemeId(Long id) {
        Iterable<StrategyTemplate> iterable = strategyTemplateRepository.search(QueryBuilders.termQuery("themeId", id));
        List<StatisVO> list = new ArrayList<>();
        List<String> names = new ArrayList<>();
        iterable.forEach(st -> {
            if(!names.contains(st.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(st.getDestId());
                vo.setName(st.getDestName());
                list.add(vo);
                names.add(st.getDestName());
            }
        });
        return list;
    }

    @Override
    public List<StatisVO> queryConditionGroup(int type) {
        if(type == StrategySearchQuery.CONDITION_TYPE_THEME){
            return conditionGroup("themeGroup","themeId","themeName",null);
        }else if(type == StrategySearchQuery.CONDITION_TYPE_ABROAD){
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("countryId",1));
            return conditionGroup("countryGroup","countryId","countryName",boolQueryBuilder);
        }else if(type == StrategySearchQuery.CONDITION_TYPE_UN_ABROAD){
            return conditionGroup("provinceGroup","provinceId","provinceName",null);
        }
        return null;
    }

    private List<StatisVO> conditionGroup(String groupName, String idField, String nameField, QueryBuilder queryBuilder){
        List<StatisVO> statisVOList = new ArrayList<>();
        List<CompositeValuesSourceBuilder<?>> sourceBuilders = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        idSource.missingBucket(true);
        sourceBuilders.add(idSource);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        nameSource.missingBucket(true);
        sourceBuilders.add(nameSource);
        CompositeAggregationBuilder compositeAggregationBuilder = new CompositeAggregationBuilder(groupName,sourceBuilders);
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);
        builder.addAggregation(compositeAggregationBuilder);
        //size不能为0
        builder.withPageable(PageRequest.of(0,1));
        if(queryBuilder != null){
            builder.withQuery(queryBuilder);
        }
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>) strategyTemplateRepository.search(builder.build());
        InternalComposite composite = search.getAggregations().get(groupName);
        StatisVO statisVO = null;
        for (CompositeAggregation.Bucket bucket : composite.getBuckets()) {
            statisVO = new StatisVO();
            if(bucket.getKey().get("id") != null) {
                statisVO.setId(Long.parseLong(bucket.getKey().get("id").toString()));
                statisVO.setName(bucket.getKey().get("name").toString());
                statisVO.setCount(bucket.getDocCount());
                statisVOList.add(statisVO);
            }
        }
        statisVOList.sort(new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                return (int) (o2.getCount() - o1.getCount());
            }
        });
        return statisVOList;
    }

    @Override
    public Page query(StrategySearchQuery qo) {
        PageRequest pageable = PageRequest.of(qo.getCurrentPage() - 1,qo.getPageSize(), Sort.by(Sort.Direction.DESC,qo.getOrderBy()));
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_THEME){
            query.must(QueryBuilders.termQuery("themeId",qo.getTypeValue()));
        }else if(qo.getType()  == StrategySearchQuery.CONDITION_TYPE_ABROAD){
            query.must(QueryBuilders.termQuery("countryId",qo.getTypeValue()));
        }else if(qo.getType()  == StrategySearchQuery.CONDITION_TYPE_UN_ABROAD){
            query.must(QueryBuilders.termQuery("provic=nceId",qo.getTypeValue()));
        }
        Page<StrategyTemplate> page = strategyTemplateRepository.search(query,pageable);
        return page;
    }

    @Override
    public List<StrategyTemplate> findByDestName(String destName) {
        return strategyTemplateRepository.findByDestName(destName);
    }
}
